﻿using System;
using System.DirectoryServices.AccountManagement;
using System.DirectoryServices.Protocols;
using System.Net;
using System.Web.UI;

namespace Core
{
    public class ActiveDirectoryUtil
    {
        /// <summary>
        /// Validates the user and password from LDAP.
        /// </summary>
        /// <param name="ldapHost">The LDAP host.</param>
        /// <param name="userName">Name of the user.</param>
        /// <param name="password">The password.</param>
        /// <returns></returns>
        public static bool ValidateUserAndPasswordFromLdap(string ldapHost, string userName, string password)
        {
            LdapDirectoryIdentifier host = new LdapDirectoryIdentifier(ldapHost);
            LdapConnection ldapConn = new LdapConnection(host);

            ldapConn.Credential = new NetworkCredential(userName, password);

            ldapConn.AuthType = AuthType.Ntlm;
            ldapConn.SessionOptions.ProtocolVersion = 3;

            ldapConn.Bind();

            return true;
        }

        /// <summary>
        /// Validates the user and password.
        /// </summary>
        /// <param name="domainName">Name of the domain.</param>
        /// <param name="userName">Name of the user.</param>
        /// <param name="password">The password.</param>
        /// <returns></returns>
        public static bool ValidateUserAndPassword(string domainName, string userName, string password)
        {
            bool isValid = false;

            if (!string.IsNullOrEmpty(userName) && !string.IsNullOrEmpty(password))
            {
                PrincipalContext adContext = new PrincipalContext(ContextType.Domain, domainName);
                using (adContext)
                {
                    isValid = adContext.ValidateCredentials(userName, password);
                }
            }

            return isValid;
        }

        /// <summary>
        /// Gets the full name.
        /// </summary>
        /// <param name="page">The page.</param>
        /// <param name="domainName">Name of the domain.</param>
        /// <param name="dummyUserName">Name of the dummy user.</param>
        /// <param name="dummyPassword">The dummy password.</param>
        /// <returns></returns>
        public static string GetFullName(Page page, string domainName, string dummyUserName, string dummyPassword)
        {
            System.Security.Principal.WindowsIdentity userIdentity = (System.Security.Principal.WindowsIdentity)page.User.Identity;
            userIdentity.Impersonate();

            string fullName = null;
            try
            {
                using (PrincipalContext context = new PrincipalContext(ContextType.Domain, domainName, dummyUserName, dummyPassword))
                {
                    using (UserPrincipal user = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, userIdentity.Name))
                    {
                        if (user != null)
                        {
                            fullName = user.DisplayName;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                fullName = "";
                ex.GetBaseException();
            }

            return fullName;
        }

        /// <summary>
        /// Gets the full name.
        /// </summary>
        /// <param name="domainName">Name of the domain.</param>
        /// <param name="userName">Name of the user.</param>
        /// <param name="dummyUserName">Name of the dummy user.</param>
        /// <param name="dummyPassword">The dummy password.</param>
        /// <returns></returns>
        public static string GetFullName(string domainName, string userName, string dummyUserName, string dummyPassword)
        {
            string fullName = null;
            try
            {
                using (PrincipalContext context = new PrincipalContext(ContextType.Domain, domainName, dummyUserName, dummyPassword))
                {
                    using (UserPrincipal user = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, userName))
                    {
                        if (user != null)
                        {
                            fullName = user.DisplayName;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                fullName = "";
                ex.GetBaseException();
                //NLogger.Instance.Warn(ex.Message);
            }

            return fullName;
        }

        /// <summary>
        /// Changes the password.
        /// </summary>
        /// <param name="domainName">Name of the domain.</param>
        /// <param name="userName">Name of the user.</param>
        /// <param name="oldPassword">The old password.</param>
        /// <param name="newPassword">The new password.</param>
        /// <returns></returns>
        public static bool ChangePassword(string domainName, string userName, string oldPassword, string newPassword)
        {
            bool isSuccess = false;

            using (PrincipalContext context = new PrincipalContext(ContextType.Domain, domainName, userName, oldPassword))
            {
                using (UserPrincipal user = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, userName))
                {
                    if (user != null)
                    {
                        user.SetPassword(newPassword);
                        user.Save();

                        isSuccess = true;
                    }
                }
            }

            return isSuccess;
        }

        /// <summary>
        /// Determines whether [is domain user] [the specified user name].
        /// </summary>
        /// <param name="userName">Name of the user.</param>
        /// <returns>
        ///   <c>true</c> if [is domain user] [the specified user name]; otherwise, <c>false</c>.
        /// </returns>
        public static bool IsDomainUser(string userName)
        {
            const bool isValid = false;

            if (userName.Length != 6)
            {
                return isValid;
            }

            //First character must be letter
            if (!Char.IsLetter(userName[0]))
            {
                return isValid;
            }

            //Second to sixth characters must be digit
            if (!Char.IsDigit(userName[1]) || !Char.IsDigit(userName[2]) ||
                !Char.IsDigit(userName[3]) || !Char.IsDigit(userName[4]) ||
                !Char.IsDigit(userName[5]))
            {
                return isValid;
            }

            return true;
        }
    }
}
